<?php
require_once 'database.php';


// Contains methods for CRUD operations in database for all model classes
class database_object{
    
    
     //Method returns all records from a distinct table
	public static function find_all() {
            
            return static::find_by_sql("SELECT * FROM ".static::$table_name);
        }
  
        //Method is used to find id from the table in the database
        public static function find_by_id($id=0) {
            

            $result_array = static::find_by_sql("SELECT * FROM ".static::$table_name." WHERE id={$id} LIMIT 1");
                        return !empty($result_array) ? array_shift($result_array) : false;
        }
  
        //Method is used to do any sql changes and returning array of the object you are looking for
        public static function find_by_sql($sql="") {
            

            $database = Database::getInstance();
            $result_set = $database->query($sql);
            $object_array = array();
            while ($row = $database->fetch_array($result_set)) {
            $object_array[] = static::instantiate($row);
            }
            return $object_array;
        }

        // This method count all objects in the database table
	public static function count_all() {
            
            
            $database = Database::getInstance();
            $sql = "SELECT COUNT(*) FROM ".static::$table_name;
            $result_set = $database->query($sql);
            $row = $database->fetch_array($result_set);
            
            return array_shift($row);
	}
        
        //Method executes the parameter sql to the database
        public static function executeSQL($sql){
            
            $database = Database::getInstance();
            $result_set = $database->query($sql);
            $array = array();
            
            while ($row = $database->fetch_array($result_set)) {
                $array[] = $row;
            }
            return $array;
  
        }

        
	// This method defines table variables to object 
	private static function instantiate($record) {
            $object = new static();
	
            // More dynamic, short-form approach:
            foreach($record as $attribute=>$value){
                if($object->has_attribute($attribute)) {
                $object->$attribute = $value;
                }
            }
            return $object;
	}
	
          // We don't care about the value, we just want to know if the key exists
	  // Will return true or false
	private function has_attribute($attribute) {
	
	  return array_key_exists($attribute, $this->attributes());
	}
        
        //Method returns an array of attribute names and their values
	protected function attributes() { 
		
	  $attributes = array();
	  foreach(static::$db_fields as $field) {
	    if(property_exists($this, $field)) {
	      $attributes[$field] = $this->$field;
	    }
	  }
	  return $attributes;
	}
	
        
        // sanitize the values before submitting by escaping the SQL chars
	protected function sanitized_attributes() {
	  $database = Database::getInstance();
	  $clean_attributes = array();

	 
          foreach($this->attributes() as $key => $value){
	    $clean_attributes[$key] = $database->escape_value($value);
	  }
	  
          return $clean_attributes;
	}
	
        // Decides wether to insert or update object/record in database. If the id != 0 it gets updated, else it will be inserted as a new record
	public function save() {
	  // A new record wont have an id yet.
	  return isset($this->id) ? $this->update() : $this->create();
	}
	
        // Preforms an insert in the database
	public function create() {
            $database = Database::getInstance();

            $attributes = $this->sanitized_attributes();
            $sql = "INSERT INTO ".static::$table_name." (";
            $sql .= join(", ", array_keys($attributes));
            $sql .= ") VALUES ('";
            $sql .= join("', '", array_values($attributes));
            $sql .= "')";
            if($database->query($sql)) {
                $this->id = $database->insert_id();
                return true;
            } else {
                return false;
            }
	}

        // Preforms an update in the database
	public function update() {
            $database = Database::getInstance();
	
            $attributes = $this->sanitized_attributes();
            $attribute_pairs = array();
            
            foreach($attributes as $key => $value) {
                $attribute_pairs[] = "{$key}='{$value}'";
            }
            
            $sql = "UPDATE ".static::$table_name." SET ";
            $sql .= join(", ", $attribute_pairs);
            $sql .= " WHERE id=". $database->escape_value($this->id);
            $database->query($sql);
            
            return ($database->affected_rows() == 1) ? true : false;
	}

        // Deletes a row in database
	public function delete() {
            $database = Database::getInstance();
            $sql = "DELETE FROM ".static::$table_name;
            $sql .= " WHERE id=". $database->escape_value($this->id);
            $sql .= " LIMIT 1";
            $database->query($sql);
            return ($database->affected_rows() == 1) ? true : false;
	
		// NB: After deleting, the instance of User still 
		// exists, even though the database entry does not.
		// This can be useful, as in:
		//   echo $user->first_name . " was deleted";
		// but, for example, we can't call $user->update() 
		// after calling $user->delete().
	}

        // Escapes SQL chars from string
        public function escape($value){
            $var = $database->escape_value($value);
            return $var;
        }

}
?>
